home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / term-source.lha / Extras / Source / term-Source.lha / termTranslate.c < prev    next >
C/C++ Source or Header  |  1995-02-07  |  23KB  |  1,125 lines

  1. /*
  2. **    termTranslate.c
  3. **
  4. **    Character translation support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Translation chunk header types. */
  13.  
  14. enum    {    TYPE_NONE, TYPE_SEND, TYPE_RECEIVE };
  15.  
  16.     /* Master translation table entry types. */
  17.  
  18. enum    {    TRANSLATION_VERBATIM, TRANSLATION_IGNORE, TRANSLATION_OTHER };
  19.  
  20.     /* Symbolic names for character codes. */
  21.  
  22. STATIC struct { STRPTR Name; UBYTE Value; } CodeTab[44] =
  23. {
  24.     {    "NUL",    0    },
  25.     {    "SOH",    1    },
  26.     {    "STX",    2    },
  27.     {    "ETX",    3    },
  28.     {    "EOT",    4    },
  29.     {    "ENQ",    5    },
  30.     {    "ACK",    6    },
  31.     {    "BEL",    7    },
  32.     {    "BS",    8    },
  33.     {    "HT",    9    },
  34.     {    "LF",    10    },
  35.     {    "VT",    11    },
  36.     {    "FF",    12    },
  37.     {    "CR",    13    },
  38.     {    "SO",    14    },
  39.     {    "SI",    15    },
  40.     {    "DLE",    16    },
  41.     {    "DC1",    17    },
  42.     {    "DC2",    18    },
  43.     {    "DC3",    19    },
  44.     {    "DC4",    20    },
  45.     {    "NAK",    21    },
  46.     {    "SYN",    22    },
  47.     {    "ETB",    23    },
  48.     {    "CAN",    24    },
  49.     {    "EM",    25    },
  50.     {    "SUB",    26    },
  51.     {    "ESC",    27    },
  52.     {    "FS",    28    },
  53.     {    "GS",    29    },
  54.     {    "RS",    30    },
  55.     {    "US",    31    },
  56.     {    "SP",    32    },
  57.     {    "DEL",    127    },
  58.     {    "SS2",    142    },
  59.     {    "SS3",    143    },
  60.     {    "DCS",    144    },
  61.     {    "CSI",    155    },
  62.     {    "ST",    156    },
  63.     {    "OSC",    157    },
  64.     {    "PM",    158    },
  65.     {    "APC",    159    },
  66.     {    "NBS",    160    },
  67.     {    "SHY",    173    }
  68. };
  69.  
  70.     /* TranslateSetup():
  71.      *
  72.      *    Set up for buffer translation.
  73.      */
  74.  
  75. VOID __regargs
  76. TranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  77. {
  78.     Handle -> LocalBuffer        = NULL;
  79.     Handle -> LocalLen        = 0;
  80.  
  81.     Handle -> SourceBuffer        = SourceBuffer;
  82.     Handle -> SourceLen        = SourceLen;
  83.  
  84.     Handle -> DestinationBuffer    = DestinationBuffer;
  85.     Handle -> DestinationLen    = DestinationLen;
  86.  
  87.     Handle -> Table            = Table;
  88. }
  89.  
  90.     /* TranslateBuffer(struct TranslationHandle *Handle):
  91.      *
  92.      *    Translate buffer contents according to
  93.      *    translation table contents.
  94.      */
  95.  
  96. LONG __regargs
  97. TranslateBuffer(struct TranslationHandle *Handle)
  98. {
  99.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  100.     register LONG                 BytesWritten    = 0;
  101.     register struct TranslationEntry    *Entry;
  102.  
  103.         /* Are we to return any translated data? */
  104.  
  105.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  106.     {
  107.             /* Decrement number of bytes in buffer. */
  108.  
  109.         Handle -> LocalLen--;
  110.  
  111.             /* Return next character. */
  112.  
  113.         *Data++ = *Handle -> LocalBuffer++;
  114.  
  115.             /* Add another byte. */
  116.  
  117.         BytesWritten++;
  118.     }
  119.  
  120.         /* Loop until done. */
  121.  
  122.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  123.     {
  124.             /* Another byte eaten. */
  125.  
  126.         Handle -> SourceLen--;
  127.  
  128.             /* Get table entry. */
  129.  
  130.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  131.         {
  132.                 /* Copy to local data area. */
  133.  
  134.             Handle -> LocalBuffer    = Entry -> String;
  135.             Handle -> LocalLen    = Entry -> Len;
  136.  
  137.                 /* Translate the data. */
  138.  
  139.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  140.             {
  141.                     /* Decrement number of bytes in buffer. */
  142.  
  143.                 Handle -> LocalLen--;
  144.  
  145.                     /* Return next character. */
  146.  
  147.                 *Data++ = *Handle -> LocalBuffer++;
  148.  
  149.                     /* Add another byte. */
  150.  
  151.                 BytesWritten++;
  152.             }
  153.         }
  154.     }
  155.  
  156.     return(BytesWritten);
  157. }
  158.  
  159.     /* NameToCode(STRPTR Name):
  160.      *
  161.      *    Translate a symbolic character code name of numeral.
  162.      */
  163.  
  164. UBYTE __regargs
  165. NameToCode(STRPTR Name)
  166. {
  167.     WORD i;
  168.  
  169.     for(i = 0 ; i < 44 ; i++)
  170.     {
  171.         if(!Stricmp(CodeTab[i] . Name,Name))
  172.             return(CodeTab[i] . Value);
  173.     }
  174.  
  175.     return((UBYTE)Atol(Name));
  176. }
  177.  
  178.     /* CodeToName(UBYTE Code):
  179.      *
  180.      *    Translate a character code into a symbolic
  181.      *    name or numeral.
  182.      */
  183.  
  184. STRPTR __regargs
  185. CodeToName(UBYTE Code)
  186. {
  187.     STATIC UBYTE Name[6];
  188.  
  189.     WORD i;
  190.  
  191.     for(i = 0 ; i < 44 ; i++)
  192.     {
  193.         if(CodeTab[i] . Value == Code)
  194.             return(CodeTab[i] . Name);
  195.     }
  196.  
  197.     SPrintf(Name,"%03ld",Code);
  198.  
  199.     return(Name);
  200. }
  201.  
  202.     /* FreeTranslationTable(struct TranslationEntry **Table):
  203.      *
  204.      *    Free a character translation table.
  205.      */
  206.  
  207. VOID __regargs
  208. FreeTranslationTable(struct TranslationEntry **Table)
  209. {
  210.     WORD i;
  211.  
  212.     for(i = 0 ; i < 256 ; i++)
  213.     {
  214.         if(Table[i])
  215.             FreeTranslationEntry(Table[i]);
  216.     }
  217.  
  218.     FreeVecPooled(Table);
  219. }
  220.  
  221.     /* AllocTranslationTable():
  222.      *
  223.      *    Allocate a character translation table.
  224.      */
  225.  
  226. struct TranslationEntry **
  227. AllocTranslationTable()
  228. {
  229.     return((struct TranslationEntry **)AllocVecPooled(sizeof(struct TranslationEntry *) * 256,MEMF_ANY|MEMF_CLEAR));
  230. }
  231.  
  232.     /* FreeTranslationEntry(struct TranslationEntry *Entry):
  233.      *
  234.      *    Free a character translation table entry.
  235.      */
  236.  
  237. VOID __regargs
  238. FreeTranslationEntry(struct TranslationEntry *Entry)
  239. {
  240.     FreeVecPooled(Entry);
  241. }
  242.  
  243.     /* TranslateString(STRPTR From,STRPTR To):
  244.      *
  245.      *    Translate a string to contain control codes
  246.      *    into a string to contain the real codes.
  247.      */
  248.  
  249. LONG __regargs
  250. TranslateString(STRPTR From,STRPTR To)
  251. {
  252.     BYTE    GotControl    = FALSE,
  253.         GotEscape    = FALSE;
  254.  
  255.     LONG    Len    = strlen(From),
  256.         Count    = 0,
  257.         i;
  258.  
  259.     for(i = 0 ; i < Len ; i++)
  260.     {
  261.         if(!GotControl && !GotEscape)
  262.         {
  263.             if(From[i] == '\\')
  264.             {
  265.                 GotControl = TRUE;
  266.  
  267.                 continue;
  268.             }
  269.  
  270.             if(From[i] == '^')
  271.             {
  272.                 GotEscape = TRUE;
  273.  
  274.                 continue;
  275.             }
  276.  
  277.             To[Count++] = From[i];
  278.         }
  279.         else
  280.         {
  281.             if(GotEscape)
  282.             {
  283.                 if(ToUpper(From[i]) >= 'A' && ToUpper(From[i]) <= '_')
  284.                     To[Count++] = ToUpper(From[i]) - '@';
  285.                 else
  286.                     To[Count++] = From[i];
  287.  
  288.                 GotEscape = FALSE;
  289.             }
  290.             else
  291.             {
  292.                 if(GotControl)
  293.                 {
  294.                     switch(ToUpper(From[i]))
  295.                     {
  296.                             /* These macro commands are plainly
  297.                              * ignored.
  298.                              */
  299.  
  300.                         case '0':
  301.                         case '1':
  302.                         case '2':
  303.                         case '3':
  304.                         case '4':
  305.                         case '5':
  306.                         case '6':
  307.  
  308.                             break;
  309.  
  310.                             /* These are macro commands and
  311.                              * not supported.
  312.                              */
  313.  
  314.                         case 'A':
  315.                         case 'C':
  316.                         case 'D':
  317.                         case 'G':
  318.                         case 'H':
  319.                         case 'I':
  320.                         case 'P':
  321.                         case 'U':
  322.                         case 'X':
  323.  
  324.                             To[Count++] = '\\';
  325.                             To[Count++] = From[i];
  326.                             break;
  327.  
  328.                             /* Translate code. */
  329.  
  330.                         case '*':
  331.  
  332.                             i++;
  333.  
  334.                             while(i < Len && From[i] == ' ')
  335.                                 i++;
  336.  
  337.                             if(i < Len)
  338.                             {
  339.                                 UBYTE DummyBuffer[5],j = 0,Char;
  340.  
  341.                                 if(From[i] >= '0' && From[i] <= '9')
  342.                                 {
  343.                                     while(j < 3 && i < Len)
  344.                                     {
  345.                                         Char = From[i++];
  346.  
  347.                                         if(Char >= '0' && Char <= '9')
  348.                                             DummyBuffer[j++] = Char;
  349.                                         else
  350.                                         {
  351.                                             i--;
  352.  
  353.                                             break;
  354.                                         }
  355.                                     }
  356.                                 }
  357.                                 else
  358.                                 {
  359.                                     while(j < 4 && i < Len)
  360.                                     {
  361.                                         Char = ToLower(From[i++]);
  362.  
  363.                                         if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  364.                                             DummyBuffer[j++] = Char;
  365.                                         else
  366.                                         {
  367.                                             i--;
  368.  
  369.                                             break;
  370.                                         }
  371.                                     }
  372.                                 }
  373.  
  374.                                 DummyBuffer[j] = 0;
  375.  
  376.                                 To[Count++] = NameToCode(DummyBuffer);
  377.                             }
  378.  
  379.                             i--;
  380.  
  381.                             break;
  382.  
  383.                             /* This is a backspace. */
  384.  
  385.                         case 'B':
  386.  
  387.                             To[Count++] = '\b';
  388.                             break;
  389.  
  390.                             /* This is a form feed. */
  391.  
  392.                         case 'F':
  393.  
  394.                             To[Count++] = '\f';
  395.                             break;
  396.  
  397.                             /* This is a line feed. */
  398.  
  399.                         case 'N':
  400.  
  401.                             To[Count++] = '\n';
  402.                             break;
  403.  
  404.                             /* This is a carriage return. */
  405.  
  406.                         case 'R':
  407.  
  408.                             To[Count++] = '\r';
  409.                             break;
  410.  
  411.                             /* This is a tab. */
  412.  
  413.                         case 'T':
  414.  
  415.                             To[Count++] = '\t';
  416.                             break;
  417.  
  418.                             /* Produce the escape character. */
  419.  
  420.                         case 'E':
  421.  
  422.                             To[Count++] = ESC;
  423.                             break;
  424.  
  425.                             /* Stuff the character into the buffer. */
  426.  
  427.                         default:
  428.  
  429.                             To[Count++] = From[i];
  430.                             break;
  431.                     }
  432.  
  433.                     GotControl = FALSE;
  434.                 }
  435.             }
  436.         }
  437.     }
  438.  
  439.     return(Count);
  440. }
  441.  
  442.     /* AllocTranslationEntry(STRPTR String):
  443.      *
  444.      *    Allocate a character translation table entry.
  445.      */
  446.  
  447. struct TranslationEntry * __regargs
  448. AllocTranslationEntry(STRPTR String)
  449. {
  450.     LONG Count = TranslateString(String,SharedBuffer);
  451.  
  452.     if(Count > 0)
  453.     {
  454.         struct TranslationEntry    *Entry;
  455.         UBYTE             Type;
  456.  
  457.         if(Count > 1)
  458.         {
  459.             Type = TRANSLATE_STRING;
  460.  
  461.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Count + 1,MEMF_ANY|MEMF_CLEAR))
  462.             {
  463.                 Entry -> String    = (STRPTR)(Entry + 1);
  464.  
  465.                 memcpy(Entry -> String,SharedBuffer,Count);
  466.             }
  467.         }
  468.         else
  469.         {
  470.             Type = TRANSLATE_SINGLE;
  471.  
  472.             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  473.             {
  474.                 Entry -> String    = &Entry -> Extra;
  475.                 Entry -> Extra    = SharedBuffer[0];
  476.             }
  477.         }
  478.  
  479.         if(Entry)
  480.         {
  481.             Entry -> Type    = Type;
  482.             Entry -> Len    = Count;
  483.  
  484.             return(Entry);
  485.         }
  486.     }
  487.  
  488.     return(NULL);
  489. }
  490.  
  491.     /* FillTranslationTable(struct TranslationEntry **Table):
  492.      *
  493.      *    Fill the translation table with defaults.
  494.      */
  495.  
  496. BYTE __regargs
  497. FillTranslationTable(struct TranslationEntry **Table)
  498. {
  499.     BYTE Success = TRUE;
  500.     WORD i;
  501.  
  502.     for(i = 0 ; Success && i < 256 ; i++)
  503.     {
  504.         if(Table[i] = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  505.         {
  506.             Table[i] -> Type    = TRANSLATE_SINGLE;
  507.             Table[i] -> String    = &Table[i] -> Extra;
  508.             Table[i] -> Extra    = i;
  509.             Table[i] -> Len        = 1;
  510.         }
  511.         else
  512.             Success = FALSE;
  513.     }
  514.  
  515.     if(!Success)
  516.     {
  517.         for(i = 0 ; i < 256 ; i++)
  518.         {
  519.             if(Table[i])
  520.             {
  521.                 FreeVecPooled(Table[i]);
  522.  
  523.                 Table[i] = NULL;
  524.             }
  525.         }
  526.     }
  527.  
  528.     return(Success);
  529. }
  530.  
  531.     /* IsStandardTable(struct TranslationEntry **Table):
  532.      *
  533.      *    Checks a translation table to see if it contains
  534.      *    standard data.
  535.      */
  536.  
  537. BYTE __regargs
  538. IsStandardTable(struct TranslationEntry **Table)
  539. {
  540.     WORD i;
  541.  
  542.     for(i = 0 ; i < 256 ; i++)
  543.     {
  544.         if(Table[i])
  545.         {
  546.             if(Table[i] -> Type != TRANSLATE_SINGLE || Table[i] -> Len != 1 || Table[i] -> String[0] != i)
  547.                 return(FALSE);
  548.         }
  549.         else
  550.             return(FALSE);
  551.     }
  552.  
  553.     return(TRUE);
  554. }
  555.  
  556.     /* TranslateBack(STRPTR From,LONG Len,STRPTR To):
  557.      *
  558.      *    Translate a precompiled translation string
  559.      *    back.
  560.      */
  561.  
  562. VOID __regargs
  563. TranslateBack(STRPTR From,LONG Len,STRPTR To)
  564. {
  565.     STATIC char TypeTable[256] =
  566.     {
  567.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 ,'b','t','n', 1 ,'f','r', 1 , 1,
  568.          1 , 1 , 1 , 1 , 1 , 1 , 1 ,1 , 1 , 1 , 1 ,'e', 1 , 1 , 1 , 1,
  569.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  570.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  571.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  572.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 ,'\\',2 , 2 , 2,
  573.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  574.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 0,
  575.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  576.          0 , 0 , 0 , 0 , 0 , 0 , 0 ,0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
  577.          0 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 0 , 2 , 2,
  578.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  579.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  580.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  581.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2,
  582.          2 , 2 , 2 , 2 , 2 , 2 , 2 ,2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2
  583.     };
  584.  
  585.     STRPTR     Buffer;
  586.     LONG    i,j,BufLen;
  587.  
  588.     for(i = j = 0 ; i < Len ; i++)
  589.     {
  590.         switch(TypeTable[From[i]])
  591.         {
  592.             case 0:    To[j++] = '\\';
  593.                 To[j++] = '*';
  594.  
  595.                 Buffer = CodeToName(From[i]);
  596.  
  597.                 BufLen = strlen(Buffer);
  598.  
  599.                 memcpy(&To[j],Buffer,BufLen);
  600.  
  601.                 j += BufLen;
  602.  
  603.                 break;
  604.  
  605.             case 1:    To[j++] = '^';
  606.                 To[j++] = From[i] + '@';
  607.                 break;
  608.  
  609.             case 2:    To[j++] = From[i];
  610.                 break;
  611.  
  612.             default:To[j++] = '\\';
  613.                 To[j++] = TypeTable[From[i]];
  614.                 break;
  615.         }
  616.     }
  617.  
  618.     To[j] = 0;
  619. }
  620.  
  621.     /* SaveTranslationTables():
  622.      *
  623.      *    Save a character translation table to a file.
  624.      */
  625.  
  626. BYTE __regargs
  627. SaveTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  628. {
  629.     BYTE    Success = FALSE,
  630.         DoIt = FALSE;
  631.     WORD    i;
  632.     LONG    Error = 0;
  633.  
  634.     for(i = 0 ; !DoIt && i < 256 ; i++)
  635.     {
  636.         if(SendTable[i] || ReceiveTable[i])
  637.             DoIt = TRUE;
  638.     }
  639.  
  640.     if(DoIt)
  641.     {
  642.         struct IFFHandle    *Handle;
  643.         UBYTE             MasterTable[256];
  644.  
  645.         for(i = 0 ; i < 256 ; i++)
  646.         {
  647.             if(SendTable[i])
  648.             {
  649.                 if(SendTable[i] -> Type == TRANSLATE_SINGLE && SendTable[i] -> Len == 1 && SendTable[i] -> String[0] == i)
  650.                     MasterTable[i] = TRANSLATION_VERBATIM;
  651.                 else
  652.                     MasterTable[i] = TRANSLATION_OTHER;
  653.             }
  654.             else
  655.                 MasterTable[i] = TRANSLATION_IGNORE;
  656.  
  657.             if(ReceiveTable[i])
  658.             {
  659.                 if(ReceiveTable[i] -> Type == TRANSLATE_SINGLE && ReceiveTable[i] -> Len == 1 && ReceiveTable[i] -> String[0] == i)
  660.                     MasterTable[i] |= TRANSLATION_VERBATIM << 4;
  661.                 else
  662.                     MasterTable[i] |= TRANSLATION_OTHER << 4;
  663.             }
  664.             else
  665.                 MasterTable[i] |= TRANSLATION_IGNORE << 4;
  666.         }
  667.  
  668.         if(Handle = AllocIFF())
  669.         {
  670.             if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  671.             {
  672.                 InitIFFasDOS(Handle);
  673.  
  674.                 if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  675.                 {
  676.                     if(!(Error = PushChunk(Handle,ID_TERM,ID_CAT,IFFSIZE_UNKNOWN)))
  677.                     {
  678.                         if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  679.                         {
  680.                             if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  681.                             {
  682.                                 struct TermInfo TermInfo;
  683.  
  684.                                 TermInfo . Version    = CONFIG_FILE_VERSION;
  685.                                 TermInfo . Revision    = CONFIG_FILE_REVISION;
  686.  
  687.                                 if(WriteChunkRecords(Handle,&TermInfo,sizeof(struct TermInfo),1))
  688.                                 {
  689.                                     if(!(Error = PopChunk(Handle)))
  690.                                     {
  691.                                         if(!(Error = PushChunk(Handle,0,ID_TRNS,256)))
  692.                                         {
  693.                                             if(WriteChunkBytes(Handle,MasterTable,256) == 256)
  694.                                             {
  695.                                                 if(!(Error = PopChunk(Handle)))
  696.                                                 {
  697.                                                     if(!(Error = PopChunk(Handle)))
  698.                                                     {
  699.                                                         struct TranslationHeader Header;
  700.  
  701.                                                         Success = TRUE;
  702.  
  703.                                                         for(i = 0 ; Success && i < 256 ; i++)
  704.                                                         {
  705.                                                             if(SendTable[i] && (MasterTable[i] & 0xF) == TRANSLATION_OTHER)
  706.                                                             {
  707.                                                                 Header . Type    = SendTable[i] -> Type;
  708.                                                                 Header . Len    = SendTable[i] -> Len;
  709.                                                                 Header . Code    = i;
  710.                                                                 Header . Pad    = 0;
  711.  
  712.                                                                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  713.                                                                 {
  714.                                                                     if(!(Error = PushChunk(Handle,0,ID_SEND,sizeof(struct TranslationHeader))))
  715.                                                                     {
  716.                                                                         if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1))
  717.                                                                         {
  718.                                                                             if(!(Error = PopChunk(Handle)))
  719.                                                                             {
  720.                                                                                 if(!(Error = PushChunk(Handle,0,ID_CHRS,SendTable[i] -> Len)))
  721.                                                                                 {
  722.                                                                                     if(WriteChunkRecords(Handle,SendTable[i] -> String,SendTable[i] -> Len,1))
  723.                                                                                     {
  724.                                                                                         if(Error = PopChunk(Handle))
  725.                                                                                             Success = FALSE;
  726.                                                                                     }
  727.                                                                                     else
  728.                                                                                     {
  729.                                                                                         Error = IoErr();
  730.  
  731.                                                                                         Success = FALSE;
  732.                                                                                     }
  733.                                                                                 }
  734.                                                                             }
  735.                                                                             else
  736.                                                                                 Success = FALSE;
  737.                                                                         }
  738.                                                                         else
  739.                                                                         {
  740.                                                                             Error = IoErr();
  741.  
  742.                                                                             Success = FALSE;
  743.                                                                         }
  744.                                                                     }
  745.  
  746.                                                                     if(Success)
  747.                                                                     {
  748.                                                                         if(PopChunk(Handle))
  749.                                                                             Success = FALSE;
  750.                                                                     }
  751.                                                                 }
  752.                                                                 else
  753.                                                                     Success = FALSE;
  754.                                                             }
  755.  
  756.                                                             if(ReceiveTable[i] && (MasterTable[i] >> 4) == TRANSLATION_OTHER)
  757.                                                             {
  758.                                                                 Header . Type    = ReceiveTable[i] -> Type;
  759.                                                                 Header . Len    = ReceiveTable[i] -> Len;
  760.                                                                 Header . Code    = i;
  761.                                                                 Header . Pad    = 0;
  762.  
  763.                                                                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  764.                                                                 {
  765.                                                                     if(!(Error = PushChunk(Handle,0,ID_RECV,sizeof(struct TranslationHeader))))
  766.                                                                     {
  767.                                                                         if(WriteChunkRecords(Handle,&Header,sizeof(struct TranslationHeader),1))
  768.                                                                         {
  769.                                                                             if(!(Error = PopChunk(Handle)))
  770.                                                                             {
  771.                                                                                 if(!(Error = PushChunk(Handle,0,ID_CHRS,ReceiveTable[i] -> Len)))
  772.                                                                                 {
  773.                                                                                     if(WriteChunkRecords(Handle,ReceiveTable[i] -> String,ReceiveTable[i] -> Len,1))
  774.                                                                                     {
  775.                                                                                         if(Error = PopChunk(Handle))
  776.                                                                                             Success = FALSE;
  777.                                                                                     }
  778.                                                                                     else
  779.                                                                                     {
  780.                                                                                         Error = IoErr();
  781.  
  782.                                                                                         Success = FALSE;
  783.                                                                                     }
  784.                                                                                 }
  785.                                                                             }
  786.                                                                             else
  787.                                                                                 Success = FALSE;
  788.                                                                         }
  789.                                                                         else
  790.                                                                         {
  791.                                                                             Error = IoErr();
  792.  
  793.                                                                             Success = FALSE;
  794.                                                                         }
  795.                                                                     }
  796.  
  797.                                                                     if(Success)
  798.                                                                     {
  799.                                                                         if(Error = PopChunk(Handle))
  800.                                                                             Success = FALSE;
  801.                                                                     }
  802.                                                                 }
  803.                                                                 else
  804.                                                                     Success = FALSE;
  805.                                                             }
  806.                                                         }
  807.                                                     }
  808.                                                 }
  809.                                             }
  810.                                             else
  811.                                                 Error = IoErr();
  812.                                         }
  813.                                     }
  814.                                 }
  815.                                 else
  816.                                     Error = IoErr();
  817.                             }
  818.                         }
  819.  
  820.                         if(Success)
  821.                         {
  822.                             if(PopChunk(Handle))
  823.                                 Success = FALSE;
  824.                         }
  825.                     }
  826.  
  827.                     CloseIFF(Handle);
  828.                 }
  829.  
  830.                 Close(Handle -> iff_Stream);
  831.  
  832.                 if(Success)
  833.                     AddProtection(Name,FIBF_EXECUTE);
  834.                 else
  835.                     DeleteFile(Name);
  836.             }
  837.             else
  838.                 Error = IoErr();
  839.  
  840.             FreeIFF(Handle);
  841.         }
  842.         else
  843.             Error = ERR_NO_MEM;
  844.     }
  845.  
  846.     if(Error)
  847.         SetIoErr(Error);
  848.  
  849.     return(Success);
  850. }
  851.  
  852.     /* LoadTranslationTable()s:
  853.      *
  854.      *    Load a translation table from a file.
  855.      */
  856.  
  857. BYTE __regargs
  858. LoadTranslationTables(STRPTR Name,struct TranslationEntry **SendTable,struct TranslationEntry **ReceiveTable)
  859. {
  860.     STATIC ULONG Stops[5 * 2] =
  861.     {
  862.         ID_TERM,    ID_VERS,
  863.         ID_TERM,    ID_TRNS,
  864.         ID_TERM,    ID_SEND,
  865.         ID_TERM,    ID_RECV,
  866.         ID_TERM,    ID_CHRS
  867.     };
  868.  
  869.     struct IFFHandle    *Handle;
  870.     BYTE             Success = FALSE;
  871.     WORD             i;
  872.  
  873.     UBYTE             MasterTable[256];
  874.     BYTE             GotMasterTable = FALSE;
  875.     LONG             Error;
  876.  
  877.     if(Handle = AllocIFF())
  878.     {
  879.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  880.         {
  881.             InitIFFasDOS(Handle);
  882.  
  883.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  884.             {
  885.                 if(!(Error = StopChunks(Handle,(LONG *)Stops,5)))
  886.                 {
  887.                     struct ContextNode        *Chunk;
  888.                     struct TermInfo             TermInfo;
  889.                     struct TranslationHeader     Header;
  890.                     BYTE                 LastType = TYPE_NONE;
  891.  
  892.                     Success = TRUE;
  893.  
  894.                     while(Success && !ParseIFF(Handle,IFFPARSE_SCAN))
  895.                     {
  896.                         Chunk = CurrentChunk(Handle);
  897.  
  898.                         switch(Chunk -> cn_ID)
  899.                         {
  900.                             case ID_VERS:
  901.  
  902.                                 if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  903.                                 {
  904.                                     if(TermInfo . Version > CONFIG_FILE_VERSION || (TermInfo . Version == CONFIG_FILE_VERSION && TermInfo . Revision > CONFIG_FILE_REVISION))
  905.                                     {
  906.                                         Error = ERR_OUTDATED;
  907.  
  908.                                         Success = FALSE;
  909.                                     }
  910.                                 }
  911.                                 else
  912.                                 {
  913.                                     Error = IoErr();
  914.  
  915.                                     Success = FALSE;
  916.                                 }
  917.  
  918.                                 break;
  919.  
  920.                             case ID_TRNS:
  921.  
  922.                                 if(ReadChunkBytes(Handle,MasterTable,256) == 256)
  923.                                     GotMasterTable = TRUE;
  924.                                 else
  925.                                 {
  926.                                     Error = IoErr();
  927.  
  928.                                     Success = FALSE;
  929.                                 }
  930.  
  931.                                 break;
  932.  
  933.                             case ID_SEND:
  934.  
  935.                                 if(LastType != TYPE_NONE)
  936.                                     Success = FALSE;
  937.                                 else
  938.                                 {
  939.                                     if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk -> cn_Size),1))
  940.                                     {
  941.                                         Error = IoErr();
  942.  
  943.                                         Success = FALSE;
  944.                                     }
  945.                                     else
  946.                                         LastType = TYPE_SEND;
  947.                                 }
  948.  
  949.                                 break;
  950.  
  951.                             case ID_RECV:
  952.  
  953.                                 if(LastType != TYPE_NONE)
  954.                                 {
  955.                                     Error = IFFERR_MANGLED;
  956.  
  957.                                     Success = FALSE;
  958.                                 }
  959.                                 else
  960.                                 {
  961.                                     if(!ReadChunkRecords(Handle,&Header,MIN(sizeof(struct TranslationHeader),Chunk -> cn_Size),1))
  962.                                     {
  963.                                         Success = FALSE;
  964.  
  965.                                         Error = IoErr();
  966.                                     }
  967.                                     else
  968.                                         LastType = TYPE_RECEIVE;
  969.                                 }
  970.  
  971.                                 break;
  972.  
  973.                             case ID_CHRS:
  974.  
  975.                                 if(LastType == TYPE_NONE)
  976.                                 {
  977.                                     Error = IFFERR_MANGLED;
  978.  
  979.                                     Success = FALSE;
  980.                                 }
  981.                                 else
  982.                                 {
  983.                                     if(ReadChunkRecords(Handle,SharedBuffer,Header . Len,1))
  984.                                     {
  985.                                         struct TranslationEntry *Entry;
  986.  
  987.                                         if(Header . Type == TRANSLATE_SINGLE)
  988.                                         {
  989.                                             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  990.                                             {
  991.                                                 Entry -> String    = &Entry -> Extra;
  992.                                                 Entry -> Extra    = SharedBuffer[0];
  993.                                             }
  994.                                         }
  995.                                         else
  996.                                         {
  997.                                             if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry) + Header . Len + 1,MEMF_ANY|MEMF_CLEAR))
  998.                                             {
  999.                                                 Entry -> String    = (STRPTR)(Entry + 1);
  1000.  
  1001.                                                 memcpy(Entry -> String,SharedBuffer,Header . Len);
  1002.                                             }
  1003.                                         }
  1004.  
  1005.                                         if(Entry)
  1006.                                         {
  1007.                                             Entry -> Type    = Header . Type;
  1008.                                             Entry -> Len    = Header . Len;
  1009.  
  1010.                                             if(LastType == TYPE_SEND)
  1011.                                                 SendTable[Header . Code]    = Entry;
  1012.                                             else
  1013.                                                 ReceiveTable[Header . Code]    = Entry;
  1014.  
  1015.                                             LastType = TYPE_NONE;
  1016.                                         }
  1017.                                         else
  1018.                                         {
  1019.                                             Error = ERR_NO_MEM;
  1020.  
  1021.                                             Success = FALSE;
  1022.                                         }
  1023.                                     }
  1024.                                     else
  1025.                                     {
  1026.                                         Error = IoErr();
  1027.  
  1028.                                         Success = FALSE;
  1029.                                     }
  1030.                                 }
  1031.  
  1032.                                 break;
  1033.                         }
  1034.                     }
  1035.                 }
  1036.  
  1037.                 CloseIFF(Handle);
  1038.             }
  1039.  
  1040.             Close(Handle -> iff_Stream);
  1041.         }
  1042.         else
  1043.             Error = IoErr();
  1044.  
  1045.         FreeIFF(Handle);
  1046.     }
  1047.     else
  1048.         Error = ERR_NO_MEM;
  1049.  
  1050.     if(Success && GotMasterTable)
  1051.     {
  1052.         struct TranslationEntry *Entry;
  1053.  
  1054.         for(i = 0 ; i < 256 ; i++)
  1055.         {
  1056.             if((MasterTable[i] & 0xF) == TRANSLATION_VERBATIM)
  1057.             {
  1058.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1059.                 {
  1060.                     Entry -> Type    = TRANSLATE_SINGLE;
  1061.                     Entry -> String    = &Entry -> Extra;
  1062.                     Entry -> Extra    = i;
  1063.                     Entry -> Len    = 1;
  1064.  
  1065.                     SendTable[i] = Entry;
  1066.                 }
  1067.                 else
  1068.                 {
  1069.                     Error = ERR_NO_MEM;
  1070.  
  1071.                     Success = FALSE;
  1072.  
  1073.                     break;
  1074.                 }
  1075.             }
  1076.  
  1077.             if((MasterTable[i] >> 4) == TRANSLATION_VERBATIM)
  1078.             {
  1079.                 if(Entry = (struct TranslationEntry *)AllocVecPooled(sizeof(struct TranslationEntry),MEMF_ANY|MEMF_CLEAR))
  1080.                 {
  1081.                     Entry -> Type    = TRANSLATE_SINGLE;
  1082.                     Entry -> String    = &Entry -> Extra;
  1083.                     Entry -> Extra    = i;
  1084.                     Entry -> Len    = 1;
  1085.  
  1086.                     ReceiveTable[i] = Entry;
  1087.                 }
  1088.                 else
  1089.                 {
  1090.                     Error = ERR_NO_MEM;
  1091.  
  1092.                     Success = FALSE;
  1093.  
  1094.                     break;
  1095.                 }
  1096.             }
  1097.         }
  1098.     }
  1099.  
  1100.     if(!Success)
  1101.     {
  1102.         for(i = 0 ; i < 256 ; i++)
  1103.         {
  1104.             if(SendTable[i])
  1105.             {
  1106.                 FreeTranslationEntry(SendTable[i]);
  1107.  
  1108.                 SendTable[i] = NULL;
  1109.             }
  1110.  
  1111.             if(ReceiveTable[i])
  1112.             {
  1113.                 FreeTranslationEntry(ReceiveTable[i]);
  1114.  
  1115.                 ReceiveTable[i] = NULL;
  1116.             }
  1117.         }
  1118.     }
  1119.  
  1120.     if(Error)
  1121.         SetIoErr(Error);
  1122.  
  1123.     return(Success);
  1124. }
  1125.